#pragma once
#include "../Dispatcher.h"
#include "../TCP/TCPServer.h"
#include "KCPClient.h"
class KCPServer : public Dispatcher
{
public:
	KCPServer();
	virtual ~KCPServer();

	bool Initialize(int port);

	void Terminate();

	void Update();

	template <class _Fx, class _Types>
	void RegisterClientConnectedCallback(_Fx&& _Func, _Types&& _User) {
		onClientConnectedEvent = std::bind(_STD forward<_Fx>(_Func), _User, std::placeholders::_1);
	}

	template <class _Fx>
	void RegisterClientConnectedCallback(_Fx&& _Func) {
		onClientConnectedEvent = std::bind(_STD forward<_Fx>(_Func), std::placeholders::_1);
	}

	void UnregisterClientConnectedCallback() {
		onClientConnectedEvent = nullptr;
	}

	template <class _Fx, class _Types>
	void RegisterClientDisconnectedCallback(_Fx&& _Func, _Types&& _User) {
		onClientDisconnectedEvent = std::bind(_STD forward<_Fx>(_Func), _User, std::placeholders::_1);
	}

	template <class _Fx>
	void RegisterClientDisconnectedCallback(_Fx&& _Func) {
		onClientDisconnectedEvent = std::bind(_STD forward<_Fx>(_Func), std::placeholders::_1);
	}

	void UnregisterClientDisconnectedCallback() {
		onClientDisconnectedEvent = nullptr;
	}

	template <class _Fx, class _Types>
	void RegisterClientReceivedCallback(_Fx&& _Func, _Types&& _User) {
		onClientReceivedEvent = std::bind(_STD forward<_Fx>(_Func), _User, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
	}

	template <class _Fx>
	void RegisterClientReceivedCallback(_Fx&& _Func) {
		onClientReceivedEvent = std::bind(_STD forward<_Fx>(_Func), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
	}

	void UnregisterClientReceivedCallback() {
		onClientReceivedEvent = nullptr;
	}

public:

	void OnClientConnected(KCPClient* client);

	void OnClientReceived(KCPClient* client, char* buffer, int len);
private:

	void OnTCPClientConnected(TCPClient* client);

	void OnTCPClientDisconnected(TCPClient* client);

	void OnTCPClientReceived(TCPClient* client, char* buffer, int len);

private:
	std::function<void(KCPClient*)> onClientConnectedEvent;
	std::function<void(KCPClient*)> onClientDisconnectedEvent;
	std::function<void(KCPClient*, char* data, int size)> onClientReceivedEvent;

private:
	TCPServer* tcpServer = nullptr;
	std::unordered_set<TCPClient*> tcpClients;
	std::unordered_set<KCPClient*> kcpClients;
};

